package com.okRPC.codec;

import com.okRPC.common.RpcRequest;
import com.okRPC.common.RpcResponse;
import com.okRPC.exception.RpcException;
import com.okRPC.protocol.Message;
import com.okRPC.protocol.MessageHeader;
import com.okRPC.protocol.MessageType;
import com.okRPC.protocol.ProtocolConstant;
import com.okRPC.serialization.RpcSerialization;
import com.okRPC.serialization.SerializationFactory;
import com.okRPC.serialization.SerializationTypeEnum;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import jdk.nashorn.internal.ir.RuntimeNode;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * Description:解码器
 * Author: Simon
 * Date: 2023/10/10
 */
public class RpcDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() < ProtocolConstant.HEADER_TOTAL_LEN) {
            // 可读的数据小于请求头总的大小 直接丢弃
            return;
        }
        // 标记 ByteBuf 读指针位置
        in.markReaderIndex();

        short magic = in.readShort();
        if (magic != ProtocolConstant.MAGIC) {
            throw new IllegalArgumentException("magic number is illegal, " + magic);
        }

        byte version = in.readByte();
        byte serializeType = in.readByte();
        byte msgType = in.readByte();
        byte status = in.readByte();
        CharSequence requestId = in.readCharSequence(ProtocolConstant.REQ_LEN, StandardCharsets.UTF_8);

        int dataLength = in.readInt();
        int readableBytes = in.readableBytes();
        if(in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }

        byte[] data = new byte[dataLength];
        in.readBytes(data);

        MessageType messageType = MessageType.findByType(msgType);
        if (messageType==null){
            return;
        }

        MessageHeader messageHeader = new MessageHeader();
        messageHeader.setMagic(magic);
        messageHeader.setLen(dataLength);
        messageHeader.setVersion(version);
        messageHeader.setSerialization(serializeType);
        messageHeader.setMessageStatus(status);
        messageHeader.setRequestId(String.valueOf(requestId));
        messageHeader.setMessageType(msgType);

        RpcSerialization rpcSerialization = SerializationFactory.getSerialization(SerializationTypeEnum.parseByType(serializeType));
        switch (messageType) {
            case REQUEST:
                RpcRequest request = rpcSerialization.deSerialize(data, RpcRequest.class);
                if (request != null) {
                    Message<RpcRequest> protocol = new Message<>();
                    protocol.setMessageHeader(messageHeader);
                    protocol.setBody(request);
                    out.add(protocol);
                }
                break;
            case RESPONSE:
                RpcResponse response = rpcSerialization.deSerialize(data, RpcResponse.class);
                if (response != null) {
                    Message<RpcResponse> protocol = new Message<>();
                    protocol.setMessageHeader(messageHeader);
                    protocol.setBody(response);
                    out.add(protocol);
                }
                break;
        }

    }
}
